package com.zhong.utils;

import com.zhong.annotation.FieldAnnotation;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 参数校验工具
 *
 * @author:zbg on 2018/5/14
 */
//java 反射 + 注解
public class ParamValidatorUtils {

    /**
     * 空校验：包括空字符、全空格字符、空指针 （结合ParamValidator注解使用:提示用的字段名字取ParamValidator注解property值）
     * 校验对象的指定字段
     *
     * @param obj        参数对象
     * @param fieldNames 校验的字段
     * @return 异常信息
     */
    public static void validNullAndBlank(Object obj, String... fieldNames) throws Exception {
        if (obj == null) {
            throw new Exception("参数对象不能为空");
        }
        Class<?> clazz = obj.getClass();
        Map<String, Field> fieldMap = getAllDeclaredFields(clazz);
        for (String fieldName : fieldNames) {
            Field field = fieldMap.get(fieldName);
            if (field == null) {
                continue;
            }
            FieldAnnotation amp = field.getAnnotation(FieldAnnotation.class);
            if (amp != null && amp.required()) {
                try {
                    Method method = clazz.getMethod("get" + StringUtils.capitalize(field.getName()));
                    Object fieldValue = method.invoke(obj);
                    if (fieldValue == null) {
                        throw new Exception(amp.name() + "不能为空");
                    } else if (fieldValue instanceof String && StringUtils.isEmpty((String) fieldValue)) {
                        throw new Exception(amp.name() + "不能为空");
                    }
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    throw new Exception("参数空校验异常");
                }
            }
        }
    }

    /**
     * 获取所有的字段，包括所有父类，除了Object
     */
    private static Map<String, Field> getAllDeclaredFields(Class<?> clazz) {
        Map<String, Field> fieldMap = new HashMap<>();
        Class<?> supClazz = clazz;
        while (!"java.lang.Object".equals(supClazz.getName()) && supClazz != null) {
            Field[] fields = supClazz.getDeclaredFields();
            for (Field field : fields) {
                fieldMap.put(field.getName(), field);
            }
            supClazz = supClazz.getSuperclass();
        }
        return fieldMap;
    }

}
